package geom;


/**
 * This class represents a vector (direction and magnitude) within some space.
 * 
 * @author Robert c. Duvall
 */
public class Vector
{
    private double myDirection;
    private double mySpeed;


    public Vector ()
    {
        this(0.0, 1.0);
    }

    public Vector (double direction, double speed)
    {
        setDirection(direction);
        setSpeed(speed);
    }

    public Vector (Coordinate source, Coordinate target)
    {
        setXYChange(target.getX() - source.getX(),
                    target.getY() - source.getY());
    }

    public Vector (Vector other)
    {
        this(other.getDirection(), other.getSpeed());
    }


    public double getSpeed ()
    {
        return mySpeed;
    }

    public double getDirection ()
    {
        return myDirection;
    }

    public double getXChange ()
    {
        return getSpeed() * Math.cos(Math.toRadians(getDirection()));
    }
    
    public double getYChange ()
    {
        return getSpeed() * Math.sin(Math.toRadians(getDirection()));
    }


    public Coordinate getNextPosition (Coordinate current)
    {
        return new Coordinate(current.getX() + getXChange(), current.getY() - getYChange());
    }

    public Vector add (Vector other)
    {
        // BUGBUG: is there an easier way?
        Vector result = new Vector();
        result.setXYChange(getXChange() + other.getXChange(),
                           getYChange() + other.getYChange());
        return result;
    }

    public Vector difference (Vector other)
    {
        // BUGBUG: is there an easier way?
        Vector result = new Vector();
        result.setXYChange(getXChange() - other.getXChange(),
                           getYChange() - other.getYChange());
        return result;
    }

    public Vector negate ()
    {
        return new Vector(-getDirection(), getSpeed());
    }


    public boolean equals (Vector other)
    {
        if (this == other)       return true;
        else if (other == null)  return false;
        else
        {
            return (getDirection() == other.getDirection()) &&
                   (getSpeed() == other.getSpeed());
        }
    }
    
    public void setSpeed (double speed) 
    {
        mySpeed = speed;
    }

    public void accelerate (double change) 
    {
        setSpeed(getSpeed() + change);
    }

    public void setDirection (double direction) 
    {
        myDirection = direction;
    }

    public void turn (double degrees) 
    {
        setDirection(getDirection() + degrees);
    }

    public void setXYChange (double dx, double dy) 
    {
        setDirection(Math.toDegrees(Math.atan2(-dy, dx)));
        setSpeed(Math.sqrt(dx * dx + dy * dy));
    }

    public String toString ()
    {
        return getClass().getName() + 
               "[dir=" + getDirection() + ",spd=" + getSpeed() + "]";
    }
}
